package pac

import (
	"encoding/hex"
	"fmt"
	"strconv"
	"strings"
	"sync"
	"time"

	"slgw_web/serial/dto"
	"slgw_web/serial/util"

	db "slgw_web/application/gormdb"

	// "github.com/goburrow/modbus"
	// "openzbox.com/driver/conn/serial"
	"openzbox.com/driver/conn/serial"
	models "openzbox.com/frame/echo/models/sl_gw01"
	"openzbox.com/protocol/modbus"
)

var (
	Test []dto.CollectSet
)

func init() {
	GetSerialInit()
	GetSerial_SlavelInit()
	Serial_Slave_DetailInit()
	//RTUClient() 不能在这触发，重启会使得tcp失败
}

func CollectNew() {

}
func RTURestart(id int64) {
	systemInfo := models.SystemInfo{}
	db := db.GetDB()
	db.First(&systemInfo)
	comType := 1
	if systemInfo.ID != 0 {
		comType = systemInfo.ComType
	}
	for i, _ := range Test {
		if Test[i].DataID == id {
			Test[i].ClientClient.Close()
			//重连
			clientClients := modbus.NewClient(Test[i].P)
			err := clientClients.Connect()
			if err != nil {
				util.Error("重新打开'" + GetCOMName(Test[i].ComName, comType) + "'失败，请检查配置情况:<br>" + err.Error())
			}
			newData := dto.CollectSet{
				ClientClient:     clientClients,
				DataID:           Test[i].DataID,
				ComName:          Test[i].ComName,
				TPITV:            Test[i].TPITV,
				Timeout:          Test[i].Timeout,
				RetryCount:       Test[i].RetryCount,
				SBTimeout:        Test[i].SBTimeout,
				P:                Test[i].P,
				IsEnd:            true,
				IsErrorBreak:     Test[i].IsErrorBreak,
				ErrorMoveToFront: Test[i].ErrorMoveToFront,
			}
			Test[i] = newData
			break // 找到后退出循环
		}
	}
}
func RTUClient() {
	// 创建Modbus主机
	//Test = Test[:0]
	systemInfo := models.SystemInfo{}
	db := db.GetDB()
	db.First(&systemInfo)
	comType := 1
	if systemInfo.ID != 0 {
		comType = systemInfo.ComType
	}
	for _, data := range util.Serial {
		if data.Agreement == "1" || data.Agreement == "4" { //modbus模式
			var p modbus.ClientProvider
			var clientClients modbus.Client
			if data.Agreement == "1" { //RTU模式
				baudRate, err := strconv.Atoi(data.BAD)
				if err != nil {
					util.Error(data.ComName + "的波特率转换失败")
				}
				dataBits, err := strconv.Atoi(data.DAB)
				if err != nil {
					util.Error(data.ComName + "的数据位转换失败")
				}
				stopBits, err := strconv.Atoi(data.STO)
				if err != nil {
					util.Error(data.ComName + "的停止位转换失败")
				}
				p = modbus.NewRTUClientProvider(
					// modbus.WithEnableLogger(),
					modbus.WithSerialConfig(serial.Config{
						Address:  data.ComName,
						BaudRate: baudRate,
						DataBits: dataBits,
						StopBits: stopBits,
						Parity:   data.CHC,
						Timeout:  time.Duration(data.Timeout) * time.Second,
					}),
				)
				clientClients = modbus.NewClient(p)
				err = clientClients.Connect()
				if err != nil {
					util.Error(data.ComName + ",modbusRtu打开'" + GetCOMName(data.ComName, comType) + "'失败，请检查配置情况:<br>" + err.Error())
				}

			} else if data.Agreement == "4" { //TCP模式
				p = modbus.NewTCPClientProvider(data.ComName)

				clientClients = modbus.NewClient(p)
				err := clientClients.Connect()
				if err != nil {
					util.Error(data.ComName + ",modbusTcp打开'" + GetCOMName(data.ComName, comType) + "'失败，重连中,err:<br>" + err.Error())
					for {
						err = clientClients.Connect()
						if err != nil {
							time.Sleep(1 * time.Second)
							util.Error(data.ComName + ",modbusTcp打开'" + GetCOMName(data.ComName, comType) + "'重连失败,err:<br>" + err.Error())
						} else {
							util.Error(data.ComName + ",modbusTcp'" + GetCOMName(data.ComName, comType) + "'重连成功")
							break
						}
					}
				}
			}
			if data.TPITV == "" || data.TPITV == "0" {
				data.TPITV = "60"

			}
			tpitv, err := strconv.Atoi(data.TPITV)
			if err != nil {
				util.Error(data.ComName + "的采集周期时间配置错误,将默认为60秒")
				tpitv = 60
			}
			test1 := dto.CollectSet{
				ClientClient:     clientClients,
				DataID:           data.ID,
				ComName:          data.ComName,
				TPITV:            tpitv,
				Timeout:          int(data.Timeout),
				SBTimeout:        int(data.SBTimeout),
				RetryCount:       data.RetryCount,
				P:                p,
				IsEnd:            true,
				IsErrorBreak:     data.IsErrorBreak,
				ErrorMoveToFront: data.ErrorMoveToFront,
			}
			Test = append(Test, test1)
		}
	}
}

// modbus发送
func GetDataTime(t dto.CollectSet) {
	//var mu sync.Mutex
	go func() {

		//mu.Lock()
		//defer mu.Unlock()
		ti := 0
		for i := range Test {
			if t.DataID == Test[i].DataID {
				ti = i
				t = Test[i]
				// Test[i].IsEnd = false
				break
			}
		}
		if Test[ti].IsEnd {
			Test[ti].IsEnd = false
			// fmt.Println("进入", t.DataID, t.IsEnd)
			// var wg sync.WaitGroup

			// wg.Add(1)
			DataID := t.DataID
			ClientClient := Test[ti].ClientClient

			//defer wg.Done()
			reGetDataTime := false //是否快速重读 true是
			for _, serial_Slave := range util.Serial_Slave {
				if serial_Slave.IsCollect == 1 {
					data2 := serial_Slave
					// data2 := util.Serial_Slave[j]
					if data2.Serial_ID == DataID {
						//获取该串口的地址位
						slaveIds, err := strconv.Atoi(data2.ModbusSlaveID)
						if err != nil {
							util.Error(data2.Name + "地址位转换失败")
						}
						slaveID := byte(slaveIds)

						for ssdi, item := range util.Serial_Slave_Detail {
							if item.Serial_ID == DataID && item.Serial_Slave_ID == data2.ID {
								//fmt.Println("k", k)
								//i3++
								//判断是否需要跳过当前id的采集
								if Test[ti].IsErrorBreak == 1 {
									isBreak := false
									for e, _ := range util.ErrorBreakList {
										list := util.ErrorBreakList[e]
										if list.Serial_Slave_ID == item.Serial_Slave_ID {
											//当前id下的集合需要跳过
											for _, serial_Slave_Detail_ID := range strings.Split(list.Serial_Slave_Detail_ID_List, ",") {
												if strconv.FormatInt(item.ID, 10) == serial_Slave_Detail_ID {
													//util.Error("当前地址无法采集，已被跳过,Name:" + item.Name + ",ID:" + strconv.FormatInt(item.ID, 10))
													isBreak = true
													//util.Error("util.ErrorBreakList", util.ErrorBreakList)
													break
												}
											}
										}
									}
									if isBreak {
										continue
									}
								}
								if Test[ti].SBTimeout == 0 {
									time.Sleep(200 * time.Millisecond)
								} else {
									time.Sleep(time.Duration(Test[ti].SBTimeout) * time.Second)
								}
								if item.ValueType == nil {
									item.ValueType = new(int)
									*item.ValueType = int(dto.UShort)
								}
								if *item.ValueType == -1 {
									//公式计算
									formula := FunFormula(*item.Formula)
									if formula != "" {
										AddDataSiemens(item, "", formula, "")
									}
								} else {
									//if *item.CollectAddressID == 136 || *item.CollectAddressID == 137 {
									address := uint16(*item.CollectAddressID) // 寄存器起始地址
									quantity := uint16(1)
									switch *item.ValueType {
									case int(dto.Bool):
										quantity = uint16(1)
									case int(dto.Short):
										quantity = uint16(1)
									case int(dto.UShort):
										quantity = uint16(1)
									case int(dto.Int32):
										quantity = uint16(2)
									case int(dto.UInt32):
										quantity = uint16(2)
									case int(dto.Long):
										quantity = uint16(4)
									case int(dto.ULong):
										quantity = uint16(4)
									case int(dto.Float32):
										quantity = uint16(2)
									case int(dto.Double):
										quantity = uint16(4)
									case int(dto.UInt32C):
										quantity = uint16(2)
									case int(dto.B48):
										quantity = uint16(3)
									}
									data3 := item.Type
									if data3 == 1 {
										//读功能码01
										// 端口被透传指令占用
										if util.StopRestart {
											StopRestartCount := 0 //200次 20s后 强制退出进行下一步 防止卡死
											for {
												if StopRestartCount > 200 {
													StopRestartCount = 0
													util.StopRestart = false
													break
												}
												if !util.StopRestart {
													StopRestartCount = 0
													break
												}
												StopRestartCount++
												time.Sleep(100 * time.Millisecond)
											}
										}

										isSucces := true
										errS := ""
										results, err := ClientClient.ReadCoils(slaveID, address, quantity)
										if err != nil {
											for k := 0; k < Test[ti].RetryCount; k++ {
												results, err = ClientClient.ReadCoils(slaveID, address, quantity)
												if err != nil {
													//fmt.Printf("重连第%d次\n", k)
													isSucces = false
													errS = err.Error()
												} else {
													isSucces = true
													break
												}
											}

										}
										if isSucces {
											if len(results) > 0 {
												// binaryStr := BytesToBinaryString(results)
												// hexString := GetBinaryString(binaryStr)
												// fmt.Println("results", results)
												// fmt.Println("binaryStr", binaryStr)
												// fmt.Println("hexString", hexString)
												hexString := GetModbusData(results)
												AddDataSiemens(item, hexString, hexString, hexString)
												// AddData(data2.Serial_ID, data2.ID, data3, hexString, item.CollectAddressID)
											} else {
												//deleteArray(data2.Serial_ID, data2.ID, data3, *item.CollectAddressID)
											}
											ErrorBreakS(item, data3)
										} else {
											//把错误的移到前面
											if Test[ti].ErrorMoveToFront == 1 {
												MoveToFront(util.Serial_Slave_Detail, ssdi)
												reGetDataTime = true
											}
											//采集失败的，如果上一次成功，把上一次的值删除
											util.Error("modbus功能码1采集失败,采集点名:" + data2.Name + "." + item.Name + ",ID:" + strconv.FormatInt(item.ID, 10) + ",错误:" + errS)
											ErrorCollect(item)
										}
										if Test[ti].IsErrorBreak == 1 { //如果开启失败跳过功能 ，失败的就跳过
											ErrorBreakF(item, data3, isSucces, DataID, data2.ID, Test[ti].ComName, data2.Name)
										}

									} else if data3 == 2 {
										//读功能码02
										// 端口被透传指令占用
										if util.StopRestart {
											StopRestartCount := 0 //200次 20s后 强制退出进行下一步 防止卡死
											for {
												if StopRestartCount > 200 {
													StopRestartCount = 0
													util.StopRestart = false
													break
												}
												if !util.StopRestart {
													StopRestartCount = 0
													break
												}
												StopRestartCount++
												time.Sleep(100 * time.Millisecond)
											}
										}
										isSucces := true
										errS := ""
										results, err := ClientClient.ReadDiscreteInputs(slaveID, address, quantity)
										if err != nil {
											for k := 0; k < Test[ti].RetryCount; k++ {
												results, err = ClientClient.ReadDiscreteInputs(slaveID, address, quantity)
												if err != nil {
													//fmt.Printf("重连第%d次\n", k)
													isSucces = false
													errS = err.Error()
												} else {
													isSucces = true
													break
												}
											}

										}
										if isSucces {
											if len(results) > 0 {
												hexString := GetModbusData(results)
												AddDataSiemens(item, hexString, hexString, hexString)
												// AddData(data2.Serial_ID, data2.ID, data3, hexString, item.CollectAddressID)
											} else {
												//deleteArray(data2.Serial_ID, data2.ID, data3, *item.CollectAddressID)
											}
											ErrorBreakS(item, data3)
										} else {
											//把错误的移到前面
											if Test[ti].ErrorMoveToFront == 1 {
												MoveToFront(util.Serial_Slave_Detail, ssdi)
												reGetDataTime = true
											}
											//采集失败的，如果上一次成功，把上一次的值删除
											util.Error("modbus功能码2采集失败,采集点名:" + data2.Name + "." + item.Name + ",ID:" + strconv.FormatInt(item.ID, 10) + ",错误:" + errS)
											ErrorCollect(item)
										}
										if Test[ti].IsErrorBreak == 1 { //如果开启失败跳过功能 ，失败的就跳过
											ErrorBreakF(item, data3, isSucces, DataID, data2.ID, Test[ti].ComName, data2.Name)
										}

									} else if data3 == 3 {
										//读功能码03
										// 端口被透传指令占用
										if util.StopRestart {
											StopRestartCount := 0 //200次 20s后 强制退出进行下一步 防止卡死
											for {
												if StopRestartCount > 200 {
													StopRestartCount = 0
													util.StopRestart = false
													break
												}
												if !util.StopRestart {
													StopRestartCount = 0
													break
												}
												StopRestartCount++
												time.Sleep(100 * time.Millisecond)
											}
										}

										isSucces := true
										errS := ""
										//fmt.Println("err1", Test[ti].IsEnd, t.IsEnd)
										results, err, s, r := ClientClient.ReadHoldingRegistersNew(slaveID, address, quantity)
										if err != nil {
											errS = err.Error()
											isSucces = false
											//fmt.Println("err1", err, data2, t, slaveIds, slaveID)
											for k := 0; k < Test[ti].RetryCount; k++ {
												time.Sleep(time.Duration(Test[ti].SBTimeout) * time.Second)
												// text := "采集点名:" + data2.Name + "." + item.Name + ",ID:" + strconv.FormatInt(item.ID, 10)
												// ClientClient
												results, err, s, r = ClientClient.ReadHoldingRegistersNew(slaveID, address, quantity)
												if err != nil {
													//fmt.Printf("重连第%d次\n", k)
													//fmt.Println("err2", err)
													isSucces = false
													errS = err.Error()
												} else {
													isSucces = true
													errS = ""
													break
												}
											}

										}
										shex := ""
										rhex := ""
										if s != nil {
											//fmt.Println("s", *s)
											shex = *s
										}
										if r != nil {
											//fmt.Println("r", *r)
											rhex = *r
										}
										text := "串口:" + Test[ti].ComName + ",采集点名:" + data2.Name + "." + item.Name + ",ID:" + strconv.FormatInt(item.ID, 10) + ".发送数据:" + shex + ",接收数据:" + rhex
										//util.WriteRTULog()
										go util.WriteRTULog(text)
										if isSucces {
											if len(results) > 0 {
												hexString, vString := "", ""
												hexString = GetModbusData(results)
												// 预先指定字节数组的长度
												byteBuffer := make([]byte, len(hexString)/2)

												// 将16进制字符串解码为字节数组
												_, err := hex.Decode(byteBuffer, []byte(hexString))
												if err != nil {
													fmt.Println("解码失败:", err)
													continue
												}
												//fmt.Println("test", test)
												//fmt.Println(item.ID, byteBuffer)
												switch *item.ValueType {
												case int(dto.Bool):
													var value bool
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.UByte):
													var value uint8
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.Short):
													byteBuffer = ChangeByte(byteBuffer, item.ValueStructure)
													var value int16
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.UShort):
													byteBuffer = ChangeByte(byteBuffer, item.ValueStructure)
													var value uint16
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.Int32):
													byteBuffer = ChangeByte(byteBuffer, item.ValueStructure)
													var value int32
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.UInt32):
													byteBuffer = ChangeByte(byteBuffer, item.ValueStructure)
													var value uint32
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.Long):
													var value int64
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.ULong):
													var value uint64
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.Float32):
													var value float32
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.Double):
													var value float64
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.UInt32C):
													var value uint32
													// fmt.Println("sss", fmt.Sprintf("%2x", byteBuffer))
													// fmt.Println("aaa", byteBuffer)
													byteBuffer2 := ConvertEndian(byteBuffer)
													hexString, vString, _ = Gethexvstring(value, byteBuffer2)
												case int(dto.B48):
													vString = hexString
												}
												AddDataSiemens(item, hexString, vString, hexString)
												//util.Error("modbus功能码3采集成功,采集点名:" + data2.Name + "." + item.Name + ",ID:" + strconv.FormatInt(item.ID, 10))
												// AddData(data2.Serial_ID, data2.ID, data3, hexString, item.CollectAddressID, vString)
											} else {
												//deleteArray(data2.Serial_ID, data2.ID, data3, *item.CollectAddressID)
											}
											ErrorBreakS(item, data3)
										} else {
											//把错误的移到前面
											if Test[ti].ErrorMoveToFront == 1 {
												MoveToFront(util.Serial_Slave_Detail, ssdi)
												reGetDataTime = true
											}
											//采集失败的，如果上一次成功，把上一次的值删除
											util.Error("modbus功能码3采集失败,采集点名:" + data2.Name + "." + item.Name + ",ID:" + strconv.FormatInt(item.ID, 10) + ",错误:" + errS)
											ErrorCollect(item)

										}

										if Test[ti].IsErrorBreak == 1 { //如果开启失败跳过功能 ，失败的就跳过
											ErrorBreakF(item, data3, isSucces, DataID, data2.ID, Test[ti].ComName, data2.Name)
										}

									} else if data3 == 4 {
										//读功能码04
										// 端口被透传指令占用
										if util.StopRestart {
											StopRestartCount := 0 //200次 20s后 强制退出进行下一步 防止卡死
											for {
												if StopRestartCount > 200 {
													StopRestartCount = 0
													util.StopRestart = false
													break
												}
												if !util.StopRestart {
													StopRestartCount = 0
													break
												}
												StopRestartCount++
												time.Sleep(100 * time.Millisecond)
											}
										}
										isSucces := true
										errS := ""
										results, err := ClientClient.ReadInputRegisters(slaveID, address, quantity)
										if err != nil {
											for k := 0; k < Test[ti].RetryCount; k++ {
												time.Sleep(time.Duration(Test[ti].SBTimeout) * time.Second)
												results, err = ClientClient.ReadInputRegisters(slaveID, address, quantity)
												if err != nil {
													//fmt.Printf("重连第%d次\n", k)
													isSucces = false
													errS = err.Error()
												} else {
													isSucces = true
													break
												}
											}

										}
										if isSucces {
											if len(results) > 0 {
												hexString, vString := "", ""
												hexString = GetModbusData(results)
												// 预先指定字节数组的长度
												byteBuffer := make([]byte, len(hexString)/2)

												// 将16进制字符串解码为字节数组
												_, err := hex.Decode(byteBuffer, []byte(hexString))
												if err != nil {
													fmt.Println("解码失败:", err)
													continue
												}

												switch *item.ValueType {
												case int(dto.Bool):
													var value bool
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.UByte):
													var value uint8
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.Short):
													var value int16
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.UShort):
													var value uint16
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.Int32):
													var value int32
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.UInt32):
													var value uint32
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.Long):
													var value int64
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.ULong):
													var value uint64
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.Float32):
													var value float32
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.Double):
													var value float64
													hexString, vString, _ = Gethexvstring(value, byteBuffer)
												case int(dto.UInt32C):
													var value uint32
													byteBuffer2 := ConvertEndian(byteBuffer)
													hexString, vString, _ = Gethexvstring(value, byteBuffer2)
												case int(dto.B48):
													vString = hexString
												}
												AddDataSiemens(item, hexString, vString, hexString)
												//AddData(data2.Serial_ID, data2.ID, data3, hexString, item.CollectAddressID, vString)
											} else {
												//deleteArray(data2.Serial_ID, data2.ID, data3, *item.CollectAddressID)
											}
											ErrorBreakS(item, data3)
										} else {
											//把错误的移到前面
											if Test[ti].ErrorMoveToFront == 1 {
												MoveToFront(util.Serial_Slave_Detail, ssdi)
												reGetDataTime = true
											}
											//采集失败的，如果上一次成功，把上一次的值删除
											util.Error("modbus功能码4采集失败,采集点名:" + data2.Name + "." + item.Name + ",ID:" + strconv.FormatInt(item.ID, 10) + ",错误:" + errS)
											ErrorCollect(item)
										}
										if Test[ti].IsErrorBreak == 1 { //如果开启失败跳过功能 ，失败的就跳过
											ErrorBreakF(item, data3, isSucces, DataID, data2.ID, Test[ti].ComName, data2.Name)
										}
									}
									//}
								}
							}
						}

						//}

					}
				} else {
					logStr := "Name:" + serial_Slave.Name + ",已配置不进行采集"
					util.IsCollectLog(logStr)
				}

			}
			if reGetDataTime && Test[ti].ErrorMoveToFront == 1 {
				Test[ti].IsEnd = true
				GetDataTime(t)
				return
			}
			Test[ti].IsEnd = true
			//	wg.Wait()
			// for i := range Test {
			// 	if t.DataID == Test[i].DataID {
			// 		Test[i].IsEnd = true
			// 		break
			// 	}
			// }
		} else {
			//fmt.Println("进不去", t.DataID, t.IsEnd, Test[ti].IsEnd)
			return
		}
		// mu.Unlock()
	}()
}

var errorBreakListMutex sync.Mutex

// 处理错误跳过
func ErrorBreakF(item models.Serial_Slave_Detail, Type int64, isSucces bool, DataID int64, data2ID int64, ComName string, data2Name string) {
	if !isSucces {
		//util.Error("util.ErrorBreakList1", util.ErrorBreakList)
		i := -1
		for e, _ := range util.ErrorBreakList {
			list := util.ErrorBreakList[e]
			if list.Serial_Slave_ID == item.Serial_Slave_ID && list.Type == Type {
				//util.Error("当前地址采集成功，剩余的地址继续采集,IDList:" + list.Serial_Slave_Detail_ID_List)
				//RemoveByID(util.ErrorBreakList, list.Serial_Slave_ID)
				i = e
				//util.Error("util.ErrorBreakList3", util.ErrorBreakList)
				break
			}
		}
		//把剩下的设备id放入集合，下次进入当前集合不在往下采集，直到当前的点位采集成功，就删除集合
		Serial_Slave_Detail_ID_List := ""
		for _, ssd := range util.Serial_Slave_Detail {
			if ssd.Serial_ID == DataID && ssd.Serial_Slave_ID == data2ID {
				if item.ID < ssd.ID && ssd.Type == Type {
					Serial_Slave_Detail_ID_List = Serial_Slave_Detail_ID_List + "," + strconv.FormatInt(ssd.ID, 10)
				}
			}
		}
		trimmedList := strings.TrimPrefix(Serial_Slave_Detail_ID_List, ",") //去除第一个,
		errorbreak := dto.ErrorBreakList{
			Serial_Slave_Detail_ID_List: trimmedList,
			Serial_Slave_ID:             item.Serial_Slave_ID,
			Type:                        Type,
		}
		//util.ErrorBreakList = append(util.ErrorBreakList, errorbreak)
		if i == -1 {
			errorBreakListMutex.Lock()
			util.ErrorBreakList = append(util.ErrorBreakList, errorbreak)
			errorBreakListMutex.Unlock()
		} else {
			errorBreakListMutex.Lock()
			if errorbreak.Serial_Slave_Detail_ID_List != util.ErrorBreakList[i].Serial_Slave_Detail_ID_List { //集合不一致的才需要替换
				util.ErrorBreakList[i] = errorbreak
				//util.Error("util.ErrorBreakList2", util.ErrorBreakList)
			}
			errorBreakListMutex.Unlock()
		}
		util.Error("当前采集点名:" + ComName + "." + data2Name + "." + item.Name + ",ID:" + strconv.FormatInt(item.ID, 10) + " 采集失败，即将跳过以下id:" + trimmedList)
		ErrorCollectList(trimmedList)
	}

}

// 采集成功的 删除跳过集合
func ErrorBreakS(item models.Serial_Slave_Detail, Type int64) {

	//采集成功，把跳过的集合删除
	for e, _ := range util.ErrorBreakList {
		list := util.ErrorBreakList[e]
		if list.Serial_Slave_ID == item.Serial_Slave_ID && list.Type == Type {
			RemoveByID(util.ErrorBreakList, list.Serial_Slave_ID, Type)
			break
		}
	}

}
func RemoveByID(errorBreakList []dto.ErrorBreakList, targetID int64, Type int64) {
	var newErrorBreakList []dto.ErrorBreakList

	for _, item := range errorBreakList {
		if item.Serial_Slave_ID != targetID || item.Type != Type {
			newErrorBreakList = append(newErrorBreakList, item)
		}
	}

	util.ErrorBreakList = newErrorBreakList
}

// //采集失败的，如果上一次成功，把上一次的值删除
// func ErrorCollect(targetID int64) {
// 	fmt.Println("util.CollectDataList_1", util.CollectDataList)
// 	var newErrorBreakList []dto.Serial_Slave_Detail_Cache

// 	for _, item := range util.CollectDataList {
// 		if item.ID != targetID {
// 			newErrorBreakList = append(newErrorBreakList, item)
// 		}
// 	}

//		util.CollectDataList = newErrorBreakList
//		fmt.Println("util.CollectDataList_2", util.CollectDataList)
//	}
func ErrorCollect(data models.Serial_Slave_Detail) {
	//fmt.Println("util.CollectDataList_1", util.CollectDataList)
	//isHave := false //当前id不存在
	for i, item := range util.CollectDataList {
		if item.ID == data.ID {
			// util.CollectDataList[i].Value = ""
			// *util.CollectDataList[i].Value2 = ""
			// *util.CollectDataList[i].Value3 = ""
			// util.CollectDataList[i].CreateTime = ""
			if util.CollectDataList[i].ValueError == nil {
				util.CollectDataList[i].ValueError = new(string)

			}
			*util.CollectDataList[i].ValueError = "EEEE"
			//isHave = true
			break
		}
	}
	// if !isHave { //不存在新增一个
	// 	ValueError := "EEEE"
	// 	test1 := dto.Serial_Slave_Detail_Cache{
	// 		ID:               data.ID,
	// 		Serial_ID:        data.Serial_ID,
	// 		Serial_Slave_ID:  data.Serial_Slave_ID,
	// 		CollectAddressID: *data.CollectAddressID,
	// 		Type:             data.Type,
	// 		Value:            "",
	// 		CreateTime:       "",
	// 		Value2:           nil,
	// 		Value3:           nil,
	// 		ValueError:       &ValueError,
	// 	}
	// 	util.CollectDataList = append(util.CollectDataList, test1)

	// }
}
func ErrorCollectList(targetIDList string) {

	for i, item := range util.CollectDataList {
		for _, targetIDString := range strings.Split(targetIDList, ",") {
			targetID, err := strconv.ParseInt(targetIDString, 10, 64)
			if err != nil {
				continue
			}
			if item.ID == targetID {
				// util.CollectDataList[i].Value = ""
				// *util.CollectDataList[i].Value2 = ""
				// *util.CollectDataList[i].Value3 = ""
				// util.CollectDataList[i].CreateTime = ""
				*util.CollectDataList[i].ValueError = "EEEE"
				break
			}
		}

	}
}

// 把出错的串口功能码去除
func deleteArray(serial_ID int64, serial_Slave_ID int64, types int64, collectAddressID int64) string {
	for i, item := range util.Serial_Slave_Detail {
		if item.Serial_ID == serial_ID && item.Serial_Slave_ID == serial_Slave_ID && item.Type == types && *item.CollectAddressID == collectAddressID {
			util.Serial_Slave_Detail = append(util.Serial_Slave_Detail[:i], util.Serial_Slave_Detail[i+1:]...)
			return item.Name
			//break
		}
	}
	return ""
}

// 将获取的数据插入对应的位置
// func AddData(serial_ID int64, serial_Slave_ID int64, types int64, collectData string, CollectAddressID *int64) {
// 	//fmt.Println("adddata", serial_ID, serial_Slave_ID, types, collectData)
// 	for i := 0; i < len(util.Serial_Slave_Detail); i++ {
// 		data := util.Serial_Slave_Detail[i]
// 		if data.Serial_ID == serial_ID && data.Serial_Slave_ID == serial_Slave_ID && data.Type == types && data.CollectAddressID == CollectAddressID {
// 			//cdata := collectData[(*data.CollectAddressID * 4) : *data.CollectAddressID*4+4] //需要采集位置的数据
// 			test1 := dto.Serial_Slave_Detail_Cache{
// 				ID:               data.ID,
// 				Serial_ID:        data.Serial_ID,
// 				Serial_Slave_ID:  data.Serial_Slave_ID,
// 				CollectAddressID: *data.CollectAddressID,
// 				Type:             data.Type,
// 				Value:            collectData,
// 				CreateTime:       time.Now().Format("2006-01-02 15:04:05"),
// 			}
// 			// 在 append 之前，遍历 collectDataListNew，根据 ID 判断是否需要覆盖
// 			updated := false
// 			for i, data := range util.CollectDataList {
// 				if data.ID == test1.ID {
// 					// 找到相同 ID 的元素，进行覆盖
// 					util.CollectDataList[i] = test1
// 					updated = true
// 					break
// 				}
// 			}
// 			// 如果没有找到相同 ID 的元素，进行追加
// 			if !updated {
// 				util.CollectDataList = append(util.CollectDataList, test1)
// 			}
// 			//collectDataListNew = append(collectDataListNew, test1)
// 		}
// 		// if len(collectDataListNew) > 0 && len(util.Serial_Slave_Detail) == len(collectDataListNew) {
// 		// 	//清空重置
// 		// 	collectDataList = collectDataListNew
// 		// 	collectDataListNew = collectDataList[:0]

//			// }
//		}
//	}
func AddDataOld(serial_ID int64, serial_Slave_ID int64, types int64, collectData string) {
	fmt.Println("adddata", serial_ID, serial_Slave_ID, types, collectData)
	for i := 0; i < len(util.Serial_Slave_Detail); i++ {
		data := util.Serial_Slave_Detail[i]
		if data.Serial_ID == serial_ID && data.Serial_Slave_ID == serial_Slave_ID && data.Type == types {
			cdata := collectData[(*data.CollectAddressID * 4) : *data.CollectAddressID*4+4] //需要采集位置的数据
			test1 := dto.Serial_Slave_Detail_Cache{
				ID:               data.ID,
				Serial_ID:        data.Serial_ID,
				Serial_Slave_ID:  data.Serial_Slave_ID,
				CollectAddressID: *data.CollectAddressID,
				Type:             data.Type,
				Value:            cdata,
				CreateTime:       time.Now().Format("2006-01-02 15:04:05"),
			}
			// 在 append 之前，遍历 collectDataListNew，根据 ID 判断是否需要覆盖
			updated := false
			for i, data := range util.CollectDataList {
				if data.ID == test1.ID {
					// 找到相同 ID 的元素，进行覆盖
					util.CollectDataList[i] = test1
					updated = true
					break
				}
			}
			// 如果没有找到相同 ID 的元素，进行追加
			if !updated {
				util.CollectDataList = append(util.CollectDataList, test1)
			}
			//collectDataListNew = append(collectDataListNew, test1)
		}
		// if len(collectDataListNew) > 0 && len(util.Serial_Slave_Detail) == len(collectDataListNew) {
		// 	//清空重置
		// 	collectDataList = collectDataListNew
		// 	collectDataListNew = collectDataList[:0]

		// }
	}
}

// 对应开启的功能码 [3,4]
func GetTypesBySerialSlaveID(serialSlaveID int64) []int64 {
	var types []int64
	for _, item := range util.Serial_Slave_Detail {
		if item.Serial_Slave_ID == serialSlaveID {
			types = append(types, item.Type)
		}
	}
	type2 := RemoveDuplicates(types)
	return type2
}

// 十进制转为8位的二进制 功能码1和2使用 比如[66 68] 转为  0100 0010 0100 0100
func BytesToBinaryString(bytes []byte) string {
	binaryString := ""
	for _, b := range bytes {
		c := fmt.Sprintf("%08b", b)
		binaryString += ReverseBinary(c) //比如 0100 0010 0100 0100   转为 0100 0010 0010 0010

	}
	return binaryString
}

// 将二进制倒序排 功能码1和2使用  比如 1234 转为 4321
func ReverseBinary(binaryStr string) string {
	var reversedBinary string
	for i := len(binaryStr) - 1; i >= 0; i-- {
		reversedBinary += string(binaryStr[i])
	}
	return reversedBinary
}

// 将每一个位转成4位二进制 功能码1和2使用 比如1101 转为 0001 0001 0000 0001
func GetBinaryString(a string) string {

	c := ""
	for i := 0; i < len(a); i++ {
		b, _ := strconv.ParseInt(a[i:i+1], 10, 64)
		c += fmt.Sprintf("%04b", b)
	}
	return c
}

var once1 sync.Once
var once2 sync.Once
var once3 sync.Once

// 串口主设置
func GetSerialInit() {
	//fmt.Println("1")
	once1.Do(func() {
		//fmt.Println("1_1")
		Serial := []models.Serial{}
		db := db.GetDB()
		//查询所有文章,以及文章的分类Preload
		db.Preload("Serial_Slave").Preload("Serial_Slave.Serial_Slave_Detail").Find(&Serial)

		util.Serial = Serial
	})
}

// 串口设备设置
func GetSerial_SlavelInit() {
	//fmt.Println("2")
	once2.Do(func() {
		//fmt.Println("2_1")
		db := db.GetDB()
		var data []models.Serial_Slave
		db.Find(&data)
		if len(data) == 0 {
			util.Error("串口设备数据未配置")
		}
		util.Serial_Slave = data
	})
}

// 串口设备功能码设置
func Serial_Slave_DetailInit() {
	//fmt.Println("3")
	once3.Do(func() {
		//fmt.Println("3_1")
		db := db.GetDB()
		var data []models.Serial_Slave_Detail
		db.Find(&data)
		if len(data) == 0 {
			util.Error("串口设备功能码数据未配置")
		}
		util.Serial_Slave_Detail = data
		var data2 []models.Serial_Slave_Detail
		for _, d := range data {
			if d.Type != 0 {
				data2 = append(data2, d)
			}

		}
	})
	//countBreak = len(data2)
	//count = len(data2)
}
